package cn.dansj.common.utils.spring.context.condition;

import cn.dansj.common.utils.lang.NotNull;
import cn.dansj.common.utils.spring.AnnotationUtils;
import cn.dansj.common.utils.spring.context.GetEnvironment;
import cn.dansj.common.utils.transfer.StringUtils;
import cn.dansj.common.utils.transfer.Verification;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Order(Ordered.HIGHEST_PRECEDENCE)
class OnPropertyCondition implements Condition {
    @Override
    public boolean matches(@NotNull ConditionContext context, @NotNull AnnotatedTypeMetadata metadata) {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName(), true);
        ConditionalOnProperty conditionalOnProperty = AnnotationUtils.synthesizeAnnotation(attributes, ConditionalOnProperty.class);
        String havingValue = conditionalOnProperty.havingValue();
        boolean matchIfMissing = conditionalOnProperty.matchIfMissing();
        String[] name = conditionalOnProperty.name();
        String prefix = conditionalOnProperty.prefix();
        List<String> keys = Arrays.stream(name).map(e -> StringUtils.concat(prefix, ".", e).replaceAll("\\.+", ".").replaceAll("^\\.*|\\.*$", "")).filter(Verification::checkNotNull).collect(Collectors.toList());
        Map<String, String> propertyMap = GetEnvironment.get();

        for (String key : keys) {
            String value = propertyMap.get(key);
            if (isNotMatch(value, havingValue, matchIfMissing)) return false;
        }
        return true;
    }

    private boolean isNotMatch(String value, String havingValue, boolean matchIfMissing) {
        return (value == null && !matchIfMissing) || (Verification.checkAllNotNull(havingValue, value) && !havingValue.equals(value));
    }
}
